package com.srtp.secureprotocol.keychain.cipherStorage;

import android.os.Build;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyInfo;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.srtp.secureprotocol.keychain.SecurityLevel;
import com.srtp.secureprotocol.keychain.cipherStorage.CipherStorage;
import com.srtp.secureprotocol.keychain.exceptions.CryptoFailedException;
import com.srtp.secureprotocol.keychain.exceptions.KeyStoreAccessException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import static com.srtp.secureprotocol.keychain.SecurityLevel.SECURE_HARDWARE;

/**
 * 密码存储基础抽象类
 * 实现Android密钥库(AndroidKeyStore)的加密存储核心功能
 */
@SuppressWarnings({"unused", "WeakerAccess", "CharsetObjectCanBeUsed", "UnusedReturnValue"})
abstract public class CipherStorageBase implements CipherStorage {
  //region 常量定义
  /** 日志标签 */
  protected static final String LOG_TAG = CipherStorageBase.class.getSimpleName();
  /** 默认密钥库类型 */
  public static final String KEYSTORE_TYPE = "AndroidKeyStore";
  /** 测试密钥别名 */
  public static final String TEST_KEY_ALIAS = KEYSTORE_TYPE + "#supportsSecureHardware";
  /** 哈希计算缓冲区大小 (4KB) */
  private static final int BUFFER_SIZE = 4 * 1024;
  /** 读写操作缓冲区大小 (16KB) */
  private static final int BUFFER_READ_WRITE_SIZE = 4 * BUFFER_SIZE;
  /** 默认字符编码 */
  public static final Charset UTF8 = Charset.forName("UTF-8");
  //endregion

  //region 成员变量
  /** 硬件支持状态同步锁 */
  protected final Object _sync = new Object();
  /** 硬件支持状态缓存（原子布尔值） */
  protected transient AtomicBoolean isSupportsSecureHardware;
  /** Strongbox支持状态同步锁 */
  protected final Object _syncStrongbox = new Object();
  /** Strongbox支持状态缓存 */
  protected transient AtomicBoolean isStrongboxAvailable;
  /** 缓存的Cipher实例（提高性能） */
  protected transient Cipher cachedCipher;
  /** 缓存的密钥库实例 */
  protected transient KeyStore cachedKeyStore;
  //endregion

  //region 接口实现方法

  /** 获取安全级别（默认为安全硬件） */
  @Override
  public SecurityLevel securityLevel() {
    return SECURE_HARDWARE;
  }

  /**
   * 计算能力级别
   * 公式：1000 * 生物识别支持 + 100 * 安全硬件支持 + 最低API级别
   * 范围：[19..1129]
   */
  @Override
  public final int getCapabilityLevel() {
    return
            (1000 * (isBiometrySupported() ? 1 : 0)) +
                    (100 * (supportsSecureHardware() ? 1 : 0)) +
                    (getMinSupportedApiLevel());
  }

  /** 检测是否支持安全硬件 */
  @Override
  public boolean supportsSecureHardware() {
    // 使用双重检查锁定优化性能
    if (null != isSupportsSecureHardware) return isSupportsSecureHardware.get();

    synchronized (_sync) {
      if (null != isSupportsSecureHardware) return isSupportsSecureHardware.get();

      isSupportsSecureHardware = new AtomicBoolean(false);
      SelfDestroyKey sdk = null;

      try {
        // 创建测试密钥验证硬件支持
        sdk = new SelfDestroyKey(TEST_KEY_ALIAS);
        final boolean newValue = validateKeySecurityLevel(SECURE_HARDWARE, sdk.key);
        isSupportsSecureHardware.set(newValue);
      } catch (Throwable ignored) {
        // 忽略异常
      } finally {
        if (null != sdk) sdk.close(); // 确保删除测试密钥
      }
    }

    return isSupportsSecureHardware.get();
  }

  /** 获取默认服务别名 */
  @Override
  public String getDefaultAliasServiceName() {
    return getCipherStorageName();
  }

  /** 从密钥库中移除指定别名密钥 */
  @Override
  public void removeKey(@NonNull final String alias) throws KeyStoreAccessException {
    final String safeAlias = getDefaultAliasIfEmpty(alias, getDefaultAliasServiceName());
    final KeyStore ks = getKeyStoreAndLoad();

    try {
      if (ks.containsAlias(safeAlias)) {
        ks.deleteEntry(safeAlias); // 删除密钥条目
      }
    } catch (GeneralSecurityException ignored) {
      // 仅当"密钥库未加载"时可能抛出异常
    }
  }
  //endregion

  //region 抽象方法（需子类实现）

  /** 获取密钥生成规范构建器 */
  @NonNull
  protected abstract KeyGenParameterSpec.Builder getKeyGenSpecBuilder(@NonNull final String alias)
          throws GeneralSecurityException;

  /** 获取密钥信息 */
  @NonNull
  protected abstract KeyInfo getKeyInfo(@NonNull final Key key) throws GeneralSecurityException;

  /** 根据规范生成密钥 */
  @NonNull
  protected abstract Key generateKey(@NonNull final KeyGenParameterSpec spec)
          throws GeneralSecurityException;

  /** 获取加密算法名称 */
  @NonNull
  protected abstract String getEncryptionAlgorithm();

  /** 获取加密转换算法 */
  @NonNull
  protected abstract String getEncryptionTransformation();
  //endregion

  //region 核心实现方法

  /** 获取缓存的Cipher实例（线程安全） */
  @NonNull
  public Cipher getCachedInstance() throws NoSuchAlgorithmException, NoSuchPaddingException {
    if (null == cachedCipher) {
      synchronized (this) {
        if (null == cachedCipher) {
          cachedCipher = Cipher.getInstance(getEncryptionTransformation());
        }
      }
    }
    return cachedCipher;
  }

  /** 检查安全级别是否满足要求 */
  protected void throwIfInsufficientLevel(@NonNull final SecurityLevel level)
          throws CryptoFailedException {

    if (!securityLevel().satisfiesSafetyThreshold(level)) {
      throw new CryptoFailedException(String.format(
              "安全级别不足 (需要 %s; 当前 %s)",
              level, securityLevel()));
    }
  }

  /** 提取或生成密钥 */
  @NonNull
  protected Key extractGeneratedKey(@NonNull final String safeAlias,
                                    @NonNull final SecurityLevel level,
                                    @NonNull final AtomicInteger retries)
          throws GeneralSecurityException {
    Key key;

    do {
      final KeyStore keyStore = getKeyStoreAndLoad();

      // 如果密钥不存在，则生成新密钥
      if (!keyStore.containsAlias(safeAlias)) {
        generateKeyAndStoreUnderAlias(safeAlias, level);
      }

      // 尝试提取密钥（支持重试）
      key = extractKey(keyStore, safeAlias, retries);
    } while (null == key);

    return key;
  }

  /** 从密钥库提取密钥（带重试机制） */
  @Nullable
  protected Key extractKey(@NonNull final KeyStore keyStore,
                           @NonNull final String safeAlias,
                           @NonNull final AtomicInteger retry)
          throws GeneralSecurityException {
    final Key key;

    // 修复Android已知bug：Invalid key blob
    try {
      key = keyStore.getKey(safeAlias, null);
    } catch (final UnrecoverableKeyException ex) {
      // 重试机制
      if (retry.getAndDecrement() > 0) {
        keyStore.deleteEntry(safeAlias); // 删除无效条目
        return null;
      }
      throw ex;
    }

    if (null == key) {
      throw new KeyStoreAccessException("提取到空密钥！");
    }

    return key;
  }

  /** 验证密钥安全级别 */
  protected boolean validateKeySecurityLevel(@NonNull final SecurityLevel level,
                                             @NonNull final Key key)
          throws GeneralSecurityException {
    return getSecurityLevel(key).satisfiesSafetyThreshold(level);
  }

  /** 获取密钥的安全级别 */
  @NonNull
  protected SecurityLevel getSecurityLevel(@NonNull final Key key) throws GeneralSecurityException {
    final KeyInfo keyInfo = getKeyInfo(key);

    // API23+支持硬件安全检测
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      final boolean insideSecureHardware = keyInfo.isInsideSecureHardware();

      if (insideSecureHardware) {
        return SECURE_HARDWARE;
      }
    }

    return SecurityLevel.SECURE_SOFTWARE; // 默认返回软件安全级别
  }

  /** 加载密钥库（带缓存） */
  @NonNull
  public KeyStore getKeyStoreAndLoad() throws KeyStoreAccessException {
    if (null == cachedKeyStore) {
      synchronized (this) {
        if (null == cachedKeyStore) {
          try {
            final KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
            keyStore.load(null); // 加载空密钥库
            cachedKeyStore = keyStore;
          } catch (final Throwable fail) {
            throw new KeyStoreAccessException("无法访问密钥库", fail);
          }
        }
      }
    }
    return cachedKeyStore;
  }

  /** 默认字符串加密（无初始化向量） */
  @NonNull
  public byte[] encryptString(@NonNull final Key key, @NonNull final String value)
          throws IOException, GeneralSecurityException {
    return encryptString(key, value, Defaults.encrypt);
  }

  /** 默认字节解密（无初始化向量） */
  @NonNull
  public String decryptBytes(@NonNull final Key key, @NonNull final byte[] bytes)
          throws IOException, GeneralSecurityException {
    return decryptBytes(key, bytes, Defaults.decrypt);
  }

  /** 字符串加密核心方法 */
  @NonNull
  protected byte[] encryptString(@NonNull final Key key, @NonNull final String value,
                                 @Nullable final EncryptStringHandler handler)
          throws IOException, GeneralSecurityException {

    final Cipher cipher = getCachedInstance();

    try (final ByteArrayOutputStream output = new ByteArrayOutputStream()) {
      // 初始化加密器（如写入IV）
      if (null != handler) {
        handler.initialize(cipher, key, output);
        output.flush();
      }

      // 加密数据
      try (final CipherOutputStream encrypt = new CipherOutputStream(output, cipher)) {
        encrypt.write(value.getBytes(UTF8));
      }

      return output.toByteArray();
    } catch (Throwable fail) {
      Log.e(LOG_TAG, fail.getMessage(), fail);
      throw fail;
    }
  }

  /** 字节解密核心方法 */
  @NonNull
  protected String decryptBytes(@NonNull final Key key, @NonNull final byte[] bytes,
                                @Nullable final DecryptBytesHandler handler)
          throws GeneralSecurityException, IOException {
    final Cipher cipher = getCachedInstance();

    try (ByteArrayInputStream in = new ByteArrayInputStream(bytes);
         ByteArrayOutputStream output = new ByteArrayOutputStream()) {
      // 初始化解密器（如读取IV）
      if (null != handler) {
        handler.initialize(cipher, key, in);
      }

      // 解密数据
      try (CipherInputStream decrypt = new CipherInputStream(in, cipher)) {
        copy(decrypt, output); // 流复制
      }

      return new String(output.toByteArray(), UTF8);
    } catch (Throwable fail) {
      Log.w(LOG_TAG, fail.getMessage(), fail);
      throw fail;
    }
  }

  /** 生成并存储密钥 */
  public void generateKeyAndStoreUnderAlias(@NonNull final String alias,
                                            @NonNull final SecurityLevel requiredLevel)
          throws GeneralSecurityException {
    Key secretKey = null;

    // 注释掉的StrongBox实现（需要API28+）
    // 优先尝试使用安全芯片生成密钥

    // 回退到常规密钥生成
    if (null == secretKey || !isStrongboxAvailable.get()) {
      try {
        secretKey = tryGenerateRegularSecurityKey(alias);
      } catch (GeneralSecurityException fail) {
        Log.e(LOG_TAG, "常规安全存储不可用", fail);
        throw fail;
      }
    }

    // 验证生成密钥的安全级别
    if (!validateKeySecurityLevel(requiredLevel, secretKey)) {
      throw new CryptoFailedException("无法生成满足安全要求的密钥");
    }
  }

  /** 生成常规安全密钥 */
  @NonNull
  protected Key tryGenerateRegularSecurityKey(@NonNull final String alias)
          throws GeneralSecurityException {
    // 检查API级别（最低Marshmallow）
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      throw new KeyStoreAccessException("API级别" + Build.VERSION.SDK_INT + "不支持常规安全密钥库");
    }

    final KeyGenParameterSpec specification = getKeyGenSpecBuilder(alias).build();
    return generateKey(specification);
  }

  /** 生成StrongBox安全密钥（需要API28+） */
  @NonNull
  protected Key tryGenerateStrongBoxSecurityKey(@NonNull final String alias)
          throws GeneralSecurityException {
    // 检查API级别（最低Pie）
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
      throw new KeyStoreAccessException("API级别" + Build.VERSION.SDK_INT + "不支持StrongBox安全密钥库");
    }

    final KeyGenParameterSpec specification = getKeyGenSpecBuilder(alias)
            .setIsStrongBoxBacked(true) // 启用StrongBox
            .build();

    return generateKey(specification);
  }
  //endregion

  //region 测试支持方法

  /** 设置Cipher实例（测试用） */
  @VisibleForTesting
  public CipherStorageBase setCipher(final Cipher cipher) {
    cachedCipher = cipher;
    return this;
  }

  /** 设置密钥库实例（测试用） */
  @VisibleForTesting
  public CipherStorageBase setKeyStore(final KeyStore keystore) {
    cachedKeyStore = keystore;
    return this;
  }
  //endregion

  //region 静态工具方法

  /** 获取安全的服务别名（处理空值） */
  @NonNull
  public static String getDefaultAliasIfEmpty(@Nullable final String service, @NonNull final String fallback) {
    return TextUtils.isEmpty(service) ? fallback : service;
  }

  /** 流复制方法（高效的大文件处理） */
  public static void copy(@NonNull final InputStream in, @NonNull final OutputStream out) throws IOException {
    final byte[] buf = new byte[BUFFER_READ_WRITE_SIZE];
    int len;

    while ((len = in.read(buf)) > 0) {
      out.write(buf, 0, len);
    }
  }
  //endregion

  //region 内部类/接口

  /** 默认加密初始化 */
  public static final class Defaults {
    public static final EncryptStringHandler encrypt = (cipher, key, output) -> {
      cipher.init(Cipher.ENCRYPT_MODE, key);
    };

    public static final DecryptBytesHandler decrypt = (cipher, key, input) -> {
      cipher.init(Cipher.DECRYPT_MODE, key);
    };
  }

  /** 初始化向量(IV)支持 */
  public static final class IV {
    /** IV长度（16字节） */
    public static final int IV_LENGTH = 16;

    /** 加密时写入IV */
    public static final EncryptStringHandler encrypt = (cipher, key, output) -> {
      cipher.init(Cipher.ENCRYPT_MODE, key);
      final byte[] iv = cipher.getIV();
      output.write(iv, 0, iv.length); // 将IV写入输出流头部
    };

    /** 解密时读取IV */
    public static final DecryptBytesHandler decrypt = (cipher, key, input) -> {
      final IvParameterSpec iv = readIv(input);
      cipher.init(Cipher.DECRYPT_MODE, key, iv);
    };

    /** 从字节数组读取IV */
    @NonNull
    public static IvParameterSpec readIv(@NonNull final byte[] bytes) throws IOException {
      if (IV_LENGTH >= bytes.length)
        throw new IOException("输入数据长度不足，无法提取IV");

      final byte[] iv = new byte[IV_LENGTH];
      System.arraycopy(bytes, 0, iv, 0, IV_LENGTH);
      return new IvParameterSpec(iv);
    }

    /** 从输入流读取IV */
    @NonNull
    public static IvParameterSpec readIv(@NonNull final InputStream inputStream) throws IOException {
      final byte[] iv = new byte[IV_LENGTH];
      final int result = inputStream.read(iv, 0, IV_LENGTH);

      if (result != IV_LENGTH)
        throw new IOException("输入流数据不足");

      return new IvParameterSpec(iv);
    }
  }

  /** 加密处理器接口 */
  public interface EncryptStringHandler {
    void initialize(@NonNull final Cipher cipher, @NonNull final Key key, @NonNull final OutputStream output)
            throws GeneralSecurityException, IOException;
  }

  /** 解密处理器接口 */
  public interface DecryptBytesHandler {
    void initialize(@NonNull final Cipher cipher, @NonNull final Key key, @NonNull final InputStream input)
            throws GeneralSecurityException, IOException;
  }

  /** 自销毁密钥（自动删除测试密钥） */
  public class SelfDestroyKey implements Closeable {
    public final String name;
    public final Key key;

    public SelfDestroyKey(@NonNull final String name) throws GeneralSecurityException {
      this(name, tryGenerateRegularSecurityKey(name));
    }

    public SelfDestroyKey(@NonNull final String name, @NonNull final Key key) {
      this.name = name;
      this.key = key;
    }

    @Override
    public void close() {
      try {
        removeKey(name); // 自动删除密钥
      } catch (KeyStoreAccessException ex) {
        Log.w(LOG_TAG, "自动删除密钥失败: " + ex.getMessage(), ex);
      }
    }
  }
  //endregion
}